package com.foreverwin.jzymes.websocket;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.foreverwin.jzymes.common.constant.Constants;
import com.foreverwin.jzymes.common.mapper.DashBoardAdviceMapper;
import com.foreverwin.jzymes.common.mapper.NcDataAdviceMapper;
import com.foreverwin.jzymes.common.mapper.SfcBatchPassLogAdviceMapper;
import com.foreverwin.jzymes.common.service.*;
import com.foreverwin.jzymes.common.util.BOHandleUtil;
import com.foreverwin.jzymes.framework.annotation.WebSocketHandler;
import com.foreverwin.jzymes.framework.event.AppEvent;
import com.foreverwin.jzymes.framework.websocket.TextMessageWebSocketWraper;
import com.foreverwin.jzymes.production.sfc.domain.SFC;
import com.foreverwin.jzymes.production.sfc.enums.ProcedureEnum;
import com.foreverwin.jzymes.production.sfc.mapper.SFCAdviceMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Map;

@WebSocketHandler(channel = "Z_DB_WIP")
public class WipHandler extends TextMessageWebSocketWraper {

    @Autowired
    IActivityRuleAdviceService activityRuleAdviceService;
    @Autowired
    IItemGroupAdviceService itemGroupAdviceService;
    @Autowired
    ICustomFieldsAdviceService customFieldsAdviceService;
    @Autowired
    ICommonService commonService;
    @Autowired
    IItemAdviceService itemAdviceService;
    @Autowired
    DashBoardAdviceMapper dashBoardAdviceMapper;
    @Autowired
    SfcBatchPassLogAdviceMapper sfcBatchPassLogAdviceMapper;
    @Autowired
    SFCAdviceMapper sfcAdviceMapper;
    @Autowired
    NcDataAdviceMapper ncDataAdviceMapper;

    private Map<String,String> activityRuleMap;

    @Override
    public void doAfterOpen(Connection connection) {
        activityRuleMap = activityRuleAdviceService.findActivityRules( getChannel() );
    }

    @Override
    public void doAfterClose() {

    }

    @Override
    public JSONObject doReceiveAndReply(String messageType, JSONObject requestParams) {
        if( "WS_INIT_DATA".equals( messageType ) ){
            return buildWipData();
        }
        return null;
    }

    @Override
    public void onAppEvent(AppEvent<?> appEvent) {

    }


    public JSONObject buildWipData(){
        String site = activityRuleMap.get( "SITE" );
        String grinds = activityRuleMap.get( "GRIND" );
        String cncs = activityRuleMap.get( "CNC" );

        String itemGroup = itemGroupAdviceService.findItemGroupBySite( site );
        List<Map<String,Object>> itemMemberList = itemGroupAdviceService.findItemGroupMember( site, itemGroup );

        JSONArray total = new JSONArray();
        JSONObject standard = new JSONObject();
        standard.put( "id", "standard" );
        total.add( standard );
        JSONObject actual = new JSONObject();
        actual.put( "id", "actual" );
        total.add( actual );
        JSONObject diff = new JSONObject();
        diff.put( "id", "diff" );
        total.add( diff );
        JSONArray detail = new JSONArray();
        JSONObject temp = new JSONObject();

        for( Map<String,Object> itemMember : itemMemberList ){
            String itemBo = (String) itemMember.get( "ITEM_BO" );
            String itemLabel = customFieldsAdviceService.findCustomValue( itemBo, Constants.ITEM_CUSTOM_FIELD_ITEM_LABEL );

            standard.put( itemLabel, activityRuleMap.get( itemLabel ) );
            actual.put( itemLabel, 0L );

            if( grinds != null ){
                String[] grindArr = grinds.split( "," );

                JSONObject t = null;
                if( temp.containsKey( grindArr[0] ) ){
                    t = temp.getJSONObject( grindArr[0] );
                }else{
                    t = new JSONObject();
                    t.put( "id", grindArr[0] );
                    temp.put( grindArr[0], t );
                    detail.add( t );
                }

                String procedureBo = BOHandleUtil.buildFieldGroupHandle( site, ProcedureEnum.GRIND.name() );
                String rawItem = customFieldsAdviceService.findCustomValue( itemBo, Constants.ITEM_CUSTOM_FIELD_RAW_ITEM );
                if( StringUtils.isNotBlank( rawItem ) ) {
                    Map<String, Object> rawItemMap = itemAdviceService.existItem(BOHandleUtil.buildItemHandleAllRev(site, rawItem));
                    List<SFC> sfcList =  sfcAdviceMapper.selectSFCListOnWork( site, procedureBo, (String) rawItemMap.get( "HANDLE" ));
                    for( SFC sfc : sfcList ){
                        if( t.containsKey( itemLabel ) ){
                            t.put( itemLabel, t.getLong( itemLabel ) + sfc.getSfcQty() - sfc.getReleasedQty() );
                        }else{
                            t.put( itemLabel, sfc.getSfcQty() - sfc.getReleasedQty() );
                        }
                    }
                }
            }

            if( cncs != null ){
                String[] cncArr = cncs.split( "," );
                JSONObject operationInfoMap = new JSONObject();
                for( String operation : cncArr ){

                    JSONObject t = null;
                    if( temp.containsKey( operation ) ){
                        t = temp.getJSONObject( operation );
                    }else{
                        t = new JSONObject();
                        t.put( "id", operation );
                        temp.put( operation, t );
                        detail.add( t );
                    }

                    String procedureBo = BOHandleUtil.buildFieldGroupHandle( site, ProcedureEnum.CNC.name() );
                    List<SFC> sfcList =  sfcAdviceMapper.selectSFCListOnWork( site, procedureBo, itemBo );
                    //List<SFC> sfcList = commonService.findCNCSfcOnWork( site, itemBo );

                    Long inQty = 0L;
                    Long outQty = 0L;
                    Long scrapQty = 0L;
                    String prevOperation = commonService.findSfcPrevOperation( site, itemBo, operation );
                    if( prevOperation == null ){
                        for( SFC sfc : sfcList ){
                            inQty = inQty + sfc.getSfcQty();
                            Long passQty = sfcBatchPassLogAdviceMapper.selectSfcPassQtyOnOperation( site, sfc.getSfc(), operation );
                            if( passQty != null ){
                                outQty = outQty + passQty;
                            }
                            Long _scrapQty = ncDataAdviceMapper.selectSfcScrapQtyOnOperation( site, sfc.getSfc(), operation );
                            if( _scrapQty != null ){
                                scrapQty = scrapQty + _scrapQty;
                            }
                        }
                    }
                    if( prevOperation != null ){
                        if( operationInfoMap.containsKey( prevOperation ) ){
                            inQty = operationInfoMap.getJSONObject( prevOperation ).getLong( "out" );
                        }else{
                            for( SFC sfc : sfcList ){
                                Long passQty = sfcBatchPassLogAdviceMapper.selectSfcPassQtyOnOperation( site, sfc.getSfc(), prevOperation );
                                if( passQty != null ){
                                    inQty = inQty + passQty;
                                }
                            }
                        }
                        for( SFC sfc : sfcList ){
                            Long passQty = sfcBatchPassLogAdviceMapper.selectSfcPassQtyOnOperation( site, sfc.getSfc(), operation );
                            if( passQty != null ){
                                outQty = outQty + passQty;
                            }
                            Long _scrapQty = ncDataAdviceMapper.selectSfcScrapQtyOnOperation( site, sfc.getSfc(), operation );
                            if( _scrapQty != null ){
                                scrapQty = scrapQty + _scrapQty;
                            }
                        }
                    }

                    if( t.containsKey( itemLabel ) ){
                        t.put( itemLabel, t.getLong( itemLabel ) + inQty - outQty - scrapQty );
                    }else{
                        t.put( itemLabel, inQty - outQty - scrapQty );
                    }

                    actual.put( itemLabel, actual.getLong( itemLabel ) + inQty - outQty - scrapQty );

                    JSONObject operationInfo = new JSONObject();
                    operationInfo.put( "in", inQty );
                    operationInfo.put( "out", outQty );
                    operationInfo.put( "wip", inQty - outQty - scrapQty );
                    operationInfoMap.put( operation, operationInfo );
                }
            }

            diff.put( itemLabel, actual.getLong( itemLabel ) - standard.getLong( itemLabel ) );
        }

        JSONObject  response = new JSONObject();
        response.put( "total", total );
        response.put( "detail", detail );

        return response;
    }

}
